package org.particlethink.controller;

import com.alibaba.excel.EasyExcel;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.particlethink.aop.Log;
import org.particlethink.aop.infos.MasterInfoById;
import org.particlethink.auth.DefaultUser;
import org.particlethink.entry.LogType;
import org.particlethink.entry.PlanStatus;
import org.particlethink.mapper.LogMapper;
import org.particlethink.mapper.ProjectUserMapper;
import org.particlethink.model.ProjectUser;
import org.particlethink.model.User;
import org.particlethink.request.ExcelListener;
import org.particlethink.request.MasterBatchMaterialRequest;
import org.particlethink.request.MasterMasterMaterialRequest;
import org.particlethink.request.MasterPlanRequest;
import org.particlethink.response.*;
import org.particlethink.service.procure.ProjectUserImpl;
import org.particlethink.utils.ListUtilsKt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Tag(name = "总计划")
@RestController
@RequestMapping("/master_plan")
public class MasterPlanController {
    @Autowired
    ProjectUserImpl projectUserSvc;

    @Autowired
    private LogMapper logMapper;

    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private ProjectUserMapper projectUserMapper;

    @Operation(summary = "总计划列表")
    @GetMapping
    public BaseResponse<PageInfo<MasterPlanResponse>> list(
            @Parameter(description = "管理层级 string")
            @RequestParam(value = "managementLevel", required = false)
            String managementLevel,
            @Parameter(description = "项目id")
            @RequestParam(value = "projectId", required = false)
            Integer projectId,
            @Parameter(description = "总计划单号")
            @RequestParam(value = "masterPlanNo", required = false)
            String masterPlanNo,
            @Parameter(description = "总计划大类id int")
            @RequestParam(value = "masterPlanCategoryId", required = false)
            Integer masterPlanCategoryId,
            @Parameter(description = "状态 int 1:待提交；2：已提交；3：已作废")
            @RequestParam(value = "status", required = false)
            PlanStatus status,
            @Parameter(description = "提交人 string")
            @RequestParam(value = "submitUserName", required = false)
            String submitUserName,
            @Parameter(description = "提交开始时间 string yyyy-MM-dd HH:mm:ss")
            @RequestParam(value = "submitStart", required = false)
            @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
            Date submitStart,
            @Parameter(description = "提交结束时间 string")
            @RequestParam(value = "submitEnd", required = false)
            @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
            Date submitEnd,
            @Parameter(description = "页码 int")
            @RequestParam(value = "pageNum", required = false)
            Integer pageNum,
            @Parameter(description = "每页数量 int")
            @RequestParam(value = "pageSize", required = false)
            Integer pageSize
    ) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();


        PageInfo<MasterPlanResponse> masterPlanPageInfo = projectUserSvc.masterPlanList(user,managementLevel, projectId, masterPlanNo, masterPlanCategoryId, status, submitUserName, submitStart, submitEnd, pageNum, pageSize);

        return BaseResponse.success(masterPlanPageInfo);
    }


    @Operation(summary = "导出总计划台账")
    @GetMapping("/export")
    public void export(
            @Parameter(description = "管理层级 string")
            @RequestParam(value = "managementLevel", required = false)
            String managementLevel,
            @Parameter(description = "项目id Integer")
            @RequestParam(value = "projectId", required = false)
            Integer projectId,
            @Parameter(description = "总计划单号")
            @RequestParam(value = "masterPlanNo", required = false)
            String masterPlanNo,
            @Parameter(description = "总计划大类id int")
            @RequestParam(value = "masterPlanCategoryId", required = false)
            Integer masterPlanCategoryId,
            @Parameter(description = "状态 int 1:待提交；2：已提交；3：已作废")
            @RequestParam(value = "status", required = false)
            PlanStatus status,
            @Parameter(description = "提交人 string")
            @RequestParam(value = "submitUserName", required = false)
            String submitUserName,
            @Parameter(description = "提交开始时间 string yyyy-MM-dd HH:mm:ss")
            @RequestParam(value = "submitStart", required = false)
            @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
            Date submitStart,
            @Parameter(description = "提交结束时间 string")
            @RequestParam(value = "submitEnd", required = false)
            @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
            Date submitEnd,
            HttpServletResponse response
    ) throws IOException {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();

        List<MasterPlanExportResponse> masterPlanPageInfo = projectUserSvc.masterPlanExport(user,managementLevel, projectId, masterPlanNo, masterPlanCategoryId, status, submitUserName, submitStart, submitEnd);


        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("总计划", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        EasyExcel.write(response.getOutputStream(), MasterPlanExportResponse.class).sheet("模板").doWrite(masterPlanPageInfo);
    }

    @Operation(summary = "总计划详情")
    @GetMapping("/{id}")
    public BaseResponse<MasterPlanDetailResponse> show(@PathVariable("id") Integer id) {
        MasterPlanDetailResponse masterPlanDetailResponse = projectUserSvc.masterPlanDetail(id);
        return BaseResponse.success(masterPlanDetailResponse);
    }

    @Operation(summary = "")
    @GetMapping("/{id}/version")
    public BaseResponse<List<MasterPlanDetailVersionResponse>> versions(@PathVariable("id") Integer id) {
        List<org.particlethink.model.Log> logs = logMapper.selectLogsByTypeAndOtherId(LogType.Master, id);
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
        List<Integer> creatorIds = logs.stream().map(org.particlethink.model.Log::getCreateBy).collect(Collectors.toList());
        Map<Integer, ProjectUser> projectUserMap = ListUtilsKt.map(projectUserMapper.selectByIds(creatorIds), ProjectUser::getId);

        List<MasterPlanDetailVersionResponse> results = new ArrayList<>();

        AtomicInteger index = new AtomicInteger(0);
        Map<String, Integer> map = new HashMap<>();
        int i = index.incrementAndGet();
        String dateFormat = yyyyMMdd.format(new Date());
        Integer count = map.getOrDefault(dateFormat, 0);
        results.add(new MasterPlanDetailVersionResponse(this.show(id).getData(), new Date(), null, "v" + i + "-" + dateFormat + String.format("%02d", count)));

        results = logs.stream().map(log ->
                {
                    try {
                        int _i = index.incrementAndGet();
                        MasterPlanDetailResponse masterPlanDetailResponse = objectMapper.readValue(log.getContent(), MasterPlanDetailResponse.class);
                        String _dateFormat = yyyyMMdd.format(log.getCreateDate());
                        Integer _count = map.getOrDefault(_dateFormat, 0);
                        map.put(_dateFormat, count + 1);
                        return new MasterPlanDetailVersionResponse(masterPlanDetailResponse, log.getCreateDate(), Optional.ofNullable(projectUserMap.get(log.getCreateBy())).orElseGet(ProjectUser::new).getName(), "v" + _i + "-" + _dateFormat + String.format("%02d", _count));
                    } catch (JsonProcessingException e) {
                        throw new RuntimeException(e);
                    }
                }
        ).collect(Collectors.toList());

        return BaseResponse.success(results);
    }


    @Operation(summary = "创建总计划")
    @PostMapping
    public BaseResponse<String> create(@RequestBody MasterPlanRequest request) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();


        projectUserSvc.createMasterPlan(user.getProjectIds(), user.getUserId(), request);
        return BaseResponse.success("");
    }


    @Operation(summary = "修改总计划")
    @PatchMapping("/{id}")
    @Log(value = LogType.Master, id = MasterInfoById.class, description = "总计划")
    public BaseResponse<String> edit(@RequestBody MasterPlanRequest request, @PathVariable("id") Integer id) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();


        projectUserSvc.updateMasterPlan(user.getProjectIds(), id, request);
        return BaseResponse.success("");
    }

    @Operation(summary = "删除总计划")
    @DeleteMapping("/{id}")
    @Log(value = LogType.Master, id = MasterInfoById.class, description = "总计划")
    public BaseResponse<String> delete(@PathVariable("id") Integer id) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();

        projectUserSvc.deleteMasterPlan(user.getProjectIds(), id);
        return BaseResponse.success("");
    }


    @Operation(summary = "提交总计划")
    @PostMapping("/{id}/submit")
    public BaseResponse<String> submit(@PathVariable("id") Integer id) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();

        projectUserSvc.submitMasterPlan(user.getProjectIds(), user.getUserId(), id);

        return BaseResponse.success(null);
    }

    @Operation(summary = "废弃总计划")
    @PostMapping("/{id}/discard")
    public BaseResponse<String> discard(@PathVariable("id") Integer id) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();


        projectUserSvc.discardMasterPlan(user.getProjectIds(), id);

        return BaseResponse.success(null);
    }

    @Operation(summary = "启用总计划")
    @PostMapping("/{id}/enable")
    public BaseResponse<String> enable(@PathVariable("id") Integer id) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();

        projectUserSvc.enableMasterPlan(user.getProjectIds(), id);

        return BaseResponse.success(null);
    }


    @Operation(summary = "总计划剩余")
    @GetMapping("/{id}/material/residue")
    public BaseResponse<List<MaterialResidueResponse>> residue(@PathVariable("id") Integer id) {
        List<MaterialResidueResponse> responses = projectUserSvc.residue(id);
        return BaseResponse.success(responses);
    }

    @Operation(summary = "导入物料")
    @PostMapping("/import/material")
    public BaseResponse<List<ImportMaterialResponse>> ImportMaterial(@RequestParam("file") MultipartFile file) throws Exception {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();


        ExcelListener<MasterMasterMaterialRequest> excelListener = new ExcelListener<>();
        EasyExcel.read(file.getInputStream(), MasterMasterMaterialRequest.class, excelListener).sheet("导入填写").doRead();
        List<MasterMasterMaterialRequest> requests = excelListener.getData();
        if (requests.size() <= 1) {
            return BaseResponse.success(new ArrayList<>());
        }

        requests.remove(0);


        List<MasterBatchMaterialRequest> reqs = requests.stream().map(req -> {
            MasterBatchMaterialRequest req2 = new MasterBatchMaterialRequest();
            req2.setMaterialNo(req.getMaterialNo());
            req2.setExpectNum(req.getExpectNum());
            req2.setRemark(req.getRemark());
            return req2;
        }).collect(Collectors.toList());

        List<ImportMaterialResponse> materialResponses = this.projectUserSvc.ImportMaterialPlan(user,reqs);

        return BaseResponse.success(materialResponses);

    }
}
